import { ChildType } from '@/pages/CodeEditor/workspace';

export default class FileItemView extends HTMLElement {
  static TagName = 'file-item-view'
  static create(): FileItemView {
    return document.createElement(this.TagName) as FileItemView;
  }
  static fromEvent(e: Event): FileItemView | null {
    const { target } = e;
    if (!(target instanceof HTMLElement)) return null;

    let ele: HTMLElement | null = target
    while (ele) {
      if (ele instanceof FileItemView) return ele;
      ele = ele.parentElement;
    }
    return ele
  }
  static observedAttributes = ["depth", "name", "type", "open", "parent_id"];
  private icon_ele = document.createElement('div');
  private name_ele = document.createElement('span');
  private name_input_ele: HTMLInputElement | null = null;
  get depth(): number {
    return Number(this.getAttribute('depth') ?? '0');
  }
  set depth(v: number) {
    let val = Number(v);
    val = Number.isNaN(val) ? 0 : Math.max(0, val);
    this.setAttribute('depth', '' + val)
  }
  get type(): ChildType {
    const val = Number(this.getAttribute('type'))
    return val in ChildType ? val : ChildType.Invalid;
  }
  set type(v: ChildType) {
    this.setAttribute('type', '' + (v in ChildType ? v : ChildType.Invalid))
  }

  get open(): boolean { return this.getAttribute('open') === 'true' }
  set open(v: boolean) { this.setAttribute('open', '' + (!!v)) }

  get name(): string { return this.getAttribute('name') ?? ""; }
  set name(v: string) { this.setAttribute('name', v) }

  get parent_id(): string { return this.getAttribute('parent_id') ?? ""; }
  set parent_id(v: string) { this.setAttribute('parent_id', v) }
  on_rename: (n: string) => void = () => { };

  private _on_name_input_keydown(e: KeyboardEvent) {
    if (e.shiftKey || e.ctrlKey || e.altKey) return;
    switch (e.key) {
      case 'Enter':
        this.on_rename?.(this.name_input_ele?.value ?? this.name)
        this._set_renaming(false);
        break;
      case 'Escape':
        this._set_renaming(false);
        break;
      default: return; // keep event propagation
    }
    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();
  }
  private _on_name_input_blur() {
    if (this._renaming)
      this.on_rename?.(this.name_input_ele?.value ?? this.name)
    this._set_renaming(false)
  }

  private _renaming = false;
  private _set_renaming(v: boolean) {
    if (this._renaming === v) return;
    this._renaming = v;
    if (v) {
      this.name_ele.remove();
      const input = this.name_input_ele = document.createElement('input');
      input.type = 'text'
      input.value = this.name;
      input.autofocus = true;
      input.disabled = false;
      input.style.color = 'white'
      input.style.fontSize = '14px'

      input.onkeydown = this._on_name_input_keydown.bind(this);
      input.onblur = this._on_name_input_blur.bind(this);
      this.appendChild(input);
      input.focus()
      input.selectionStart = 0;
      input.selectionEnd = this.name.length;
    } else {
      this.name_input_ele?.remove();
      this.appendChild(this.name_ele);
    }
    this.draggable = !this._renaming
  }
  connectedCallback() {
    this.style.display = 'flex';
    this.style.cursor = 'pointer';
    this.style.userSelect = 'none';
    this.style.height = '23px';
    this.style.alignItems = 'center';
    this.style.outline = 'none';
    this.tabIndex = -1;
    this.draggable = true;
    this.onfocus = () => this.onkeydown = e => {
      if (e.key === 'F2' && !e.shiftKey && !e.ctrlKey && !e.altKey) {
        this._set_renaming(true)
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
      }
    }
    this.onblur = () => {
      this.onkeydown = null
    };

    this.icon_ele.style.width = this.style.height
    this.icon_ele.style.height = this.style.height
    this.icon_ele.style.lineHeight = this.style.height
    this.icon_ele.style.textAlign = 'center'
    this.icon_ele.style.pointerEvents = 'none'
    this.appendChild(this.icon_ele);

    this.name_ele.style.flex = '1';
    this.name_ele.style.pointerEvents = 'none'
    this.appendChild(this.name_ele);
  }
  disconnectedCallback() { }
  adoptedCallback() { }
  attributeChangedCallback(name: string, oldValue: string, newValue: string) {
    switch (name) {
      case 'depth':
        const depth = Number(newValue);
        this.name_ele.style.fontWeight = depth === 0 ? 'bold' : 'normal';
        this.icon_ele.style.marginLeft = '' + (depth * 10) + 'px';
        break;
      case 'name':
        this.name_ele.innerText = newValue;
        break;
      case 'open':
      case 'type':
        const icon = this.type === ChildType.Dir ? (this.open ? "⌵" : "＞") : '　';
        this.icon_ele.innerText = icon;
    }
  }
}

customElements.define(FileItemView.TagName, FileItemView)